/*
 * CollisionInfo.h
 *
 * Created 7/4/2009 By Johnny Huynh
 *
 * Version 00.00.01 7/4/2009
 *
 * Copyright Information:
 * All content copyright © 2008 Johnny Huynh. All rights reserved.
 */
 
 /**
  * The CollisionInfo class is created to strictly contain information about collisions;
  */

 #ifndef COLLISIONINFO_H
 #define COLLISIONINFO_H
 
 template <typename TYPENAME> class CollisionInfo;
 
 #include "OpenGL_Headers.h"
 #include "Vector3.h"
 
 typedef CollisionInfo<GLfloat> CollisionInfof;
 typedef CollisionInfo<GLdouble> CollisionInfod;
 
 template <typename TYPENAME>
 class CollisionInfo
 {
 // Data Members
 public:
    TYPENAME overlapping_extent;        // the length of the intersection overlap on the axis formed by the difference 
                                        // between displacementA and displacementB; if overlapping_extent is less than
                                        // zero, then the two objects currently do not intersect.
                                        // Should be changed to reverse_velocity_extent; the extent has since been changed
                                        // into the magnitude the objects need to move in the direction opposite to their
                                        // velocities to escape intersection.
    // We use displacement synonymously with the current position minus the previous position of an object; one may
    // also refer to this as the velocity of the object for the current round of collision detection.
    Vector3<TYPENAME> displacementA;    // displacement of the first object used to calculate the overlapping_extent
    Vector3<TYPENAME> displacementB;    // displacement of the second object used to calculate the overlapping_extent
    OBB<TYPENAME> obbA;
    OBB<TYPENAME> obbB;
    GL_Triangle<TYPENAME> triangleA;
    GL_Triangle<TYPENAME> triangleB;
 
 // Local Functions
    CollisionInfo( const TYPENAME& overlapping_extent, //= 0.0f, 
                   const Vector3<TYPENAME>& displacementA,// = Vector3<TYPENAME>( 0.0f, 0.0f, 0.0f ), 
                   const Vector3<TYPENAME>& displacementB,// = Vector3<TYPENAME>( 0.0f, 0.0f, 0.0f ),
                   const OBB<TYPENAME>& obbA,
                   const OBB<TYPENAME>& obbB,
                   const GL_Triangle<TYPENAME>& triangleA,
                   const GL_Triangle<TYPENAME>& triangleB );
    CollisionInfo( const CollisionInfo<TYPENAME>& c_info );
    ~CollisionInfo();
    inline CollisionInfo<TYPENAME>& operator=( const CollisionInfo<TYPENAME>& c_info );
 
 // Friend Functions
    template <typename TYPENAME> friend inline bool operator==( const CollisionInfo<TYPENAME>& c_info_A,
                                                                const CollisionInfo<TYPENAME>& c_info_B );
    template <typename TYPENAME> friend inline bool operator<( const CollisionInfo<TYPENAME>& c_info_A,
                                                               const CollisionInfo<TYPENAME>& c_info_B );
    template <typename TYPENAME> friend inline bool operator>( const CollisionInfo<TYPENAME>& c_info_A,
                                                               const CollisionInfo<TYPENAME>& c_info_B );
    template <typename TYPENAME> friend inline bool operator<=( const CollisionInfo<TYPENAME>& c_info_A,
                                                                const CollisionInfo<TYPENAME>& c_info_B );
    template <typename TYPENAME> friend inline bool operator>=( const CollisionInfo<TYPENAME>& c_info_A,
                                                                const CollisionInfo<TYPENAME>& c_info_B );
 };
 
 /** LOCAL FUNCTIONS **/
 
 /**
  * Constructor
  */
 template <typename TYPENAME>
 CollisionInfo<TYPENAME>::CollisionInfo( const TYPENAME& overlapping_extent, 
                                         const Vector3<TYPENAME>& displacementA, const Vector3<TYPENAME>& displacementB,
                                         const OBB<TYPENAME>& obbA, const OBB<TYPENAME>& obbB,
                                         const GL_Triangle<TYPENAME>& triangleA,
                                         const GL_Triangle<TYPENAME>& triangleB )
                                        : overlapping_extent( overlapping_extent ),
                                          displacementA( displacementA ),
                                          displacementB( displacementB ),
                                          obbA( obbA ),
                                          obbB( obbB ),
                                          triangleA( triangleA ),
                                          triangleB( triangleB )
 {
    
 }
 
 /**
  * Copy Constructor
  */
 template <typename TYPENAME>
 CollisionInfo<TYPENAME>::CollisionInfo( const CollisionInfo<TYPENAME>& c_info )
                                        : overlapping_extent( c_info.overlapping_extent ),
                                          displacementA( c_info.displacementA ),
                                          displacementB( c_info.displacementB ),
                                          obbA( c_info.obbA ),
                                          obbB( c_info.obbB ),
                                          triangleA( c_info.triangleA ),
                                          triangleB( c_info.triangleB )
 {
    
 }
 
 /**
  * Destructor
  */
 template <typename TYPENAME>
 CollisionInfo<TYPENAME>::~CollisionInfo()
 {
    
 }
 
 /**
  * Copy Function
  */
 template <typename TYPENAME>
 inline CollisionInfo<TYPENAME>& CollisionInfo<TYPENAME>::operator=( const CollisionInfo<TYPENAME>& c_info )
 {
    memcpy( this, &c_info, sizeof( CollisionInfo<TYPENAME> ) );
    return *this;
 }
 
 /**
  * operator==() returns true if the two specified CollisionInfos contain the same value for overlapping_extent;
  * otherwise, false is returned.
  *
  * @param (const CollisionInfo<TYPENAME>&) c_info_A
  * @param (const CollisionInfo<TYPENAME>&) c_info_B
  * @return bool
  */
 template <typename TYPENAME> 
 inline bool operator==( const CollisionInfo<TYPENAME>& c_info_A, const CollisionInfo<TYPENAME>& c_info_B )
 {
    return c_info_A.overlapping_extent == c_info_B.overlapping_extent;
 }
 
 /**
  * operator<() returns true if the overlapping_extent of the specified c_info_A is less than that of
  * the specified c_info_B; otherwise, false is returned.
  *
  * @param (const CollisionInfo<TYPENAME>&) c_info_A
  * @param (const CollisionInfo<TYPENAME>&) c_info_B
  * @return bool
  */
 template <typename TYPENAME> 
 inline bool operator<( const CollisionInfo<TYPENAME>& c_info_A, const CollisionInfo<TYPENAME>& c_info_B )
 {
    return c_info_A.overlapping_extent < c_info_B.overlapping_extent;
 }
 
 /**
  * operator>() returns true if the overlapping_extent of the specified c_info_A is greater than that of
  * the specified c_info_B; otherwise, false is returned.
  *
  * @param (const CollisionInfo<TYPENAME>&) c_info_A
  * @param (const CollisionInfo<TYPENAME>&) c_info_B
  * @return bool
  */
 template <typename TYPENAME>
 inline bool operator>( const CollisionInfo<TYPENAME>& c_info_A, const CollisionInfo<TYPENAME>& c_info_B )
 {
    return c_info_A.overlapping_extent > c_info_B.overlapping_extent;
 }
 
 /**
  * operator<=() returns true if the overlapping_extent of the specified c_info_A is less than or equal to 
  * that of the specified c_info_B; otherwise, false is returned.
  *
  * @param (const CollisionInfo<TYPENAME>&) c_info_A
  * @param (const CollisionInfo<TYPENAME>&) c_info_B
  * @return bool
  */
 template <typename TYPENAME> 
 inline bool operator<=( const CollisionInfo<TYPENAME>& c_info_A, const CollisionInfo<TYPENAME>& c_info_B )
 {
    return c_info_A.overlapping_extent <= c_info_B.overlapping_extent;
    // c_info_A < c_info_B || c_info_A == c_info_B;
 }
 
 /**
  * operator>=() returns true if the overlapping_extent of the specified c_info_A is greater than or equal to
  * that of the specified c_info_B; otherwise, false is returned.
  *
  * @param (const CollisionInfo<TYPENAME>&) c_info_A
  * @param (const CollisionInfo<TYPENAME>&) c_info_B
  * @return bool
  */
 template <typename TYPENAME>
 inline bool operator>=( const CollisionInfo<TYPENAME>& c_info_A, const CollisionInfo<TYPENAME>& c_info_B )
 {
    return c_info_A.overlapping_extent >= c_info_B.overlapping_extent;
    // c_info_A > c_info_B || c_info_A == c_info_B;
 }
 
 #endif // COLLISIONINFO_H